package com.ep.thirdPlatformProject.oa.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.ep.thirdPlatformProject.dhg.entity.*;
import com.ep.thirdPlatformProject.erp.entity.budget.ErpBudgetDetailEntity;
import com.ep.thirdPlatformProject.erp.entity.vo.ErpBudgetResultVo;
import com.ep.thirdPlatformProject.oa.service.OACompanyService;
import com.ep.thirdPlatformProject.system.aop.SyncRecordLog;
import com.ep.thirdPlatformProject.system.enums.OASyncLogEnum;
import com.ep.thirdPlatformProject.system.config.oa.WorkflowFormProperties;
import com.ep.thirdPlatformProject.oa.entity.*;
import com.ep.thirdPlatformProject.oa.enums.WorkflowEnum;
import com.ep.thirdPlatformProject.oa.service.HrmResourceService;
import com.ep.thirdPlatformProject.oa.service.OAApiService;
import com.ep.thirdPlatformProject.oa.service.WorkFlowService;
import com.ep.thirdPlatformProject.oa.util.OACommonEntityUtil;
import com.ep.thirdPlatformProject.oa.util.OAHrmTemplateUtil;
import com.ep.thirdPlatformProject.system.util.MailUtil;
import com.xxl.job.core.context.XxlJobHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import weaver.hrm.webservice.DepartmentBean;
import weaver.hrm.webservice.SubCompanyBean;
import weaver.hrm.webservice.UserBean;
import weaver.workflow.webservices.WorkflowRequestInfo;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Supplier;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class OAApiServiceImpl implements OAApiService {

    private final WorkFlowService workFlowService;

    private final HrmResourceService hrmResourceService;

    private final OACommonEntityUtil oaCommonEntityUtil;

    private final WorkflowFormProperties workflowFormProperties;

    private final OACompanyService oaCompanyService;

    private final MailUtil mailUtil;

    /**
     * 构建入职工作流程
     *
     * @param entity 实体
     * @return {@link String }
     */
    @Override
    @SyncRecordLog(logType = OASyncLogEnum.OA_SYNC_ONBOARDING_PERSON, dateLimit = true)
    public String constructOnboardingWorkFLow(DhgEmployeeEntity entity) {
        return constructCommonWorkFlow(entity.getCreateEmpNo(),
                () -> hrmResourceService.firstSaveOAUser(entity),
                (targetItem, targetCreatorId) -> buildOnboardingRequestInfo(targetItem, targetCreatorId, DateUtil.formatDate(entity.getEntryDate()), entity.getNeedAttendance())
        );
    }

    /**
     * 构建跨工作流程
     *
     * @param entity 实体
     * @return {@link String }
     */
    @Override
    @SyncRecordLog(logType = OASyncLogEnum.OA_SYNC_TRANS_POST_PERSON, dateLimit = true)
    public String constructTransWorkFlow(DhgEmployeeTransEntity entity) {
        return constructCommonWorkFlow(entity.getCreateEmpNo(),
                () -> hrmResourceService.getHrmServiceEmpInfoByCode(entity.getEmpNo()),
                (targetItem, targetCreatorId) -> buildTransFormRequestInfo(targetItem, targetCreatorId, entity)
        );
    }

    @Override
    @SyncRecordLog(logType = OASyncLogEnum.OA_SYNC_LEAVE_PERSON, dateLimit = true)
    public String constructLeaveWorkFlow(DhgEmployeeLeaveEntity entity) {
        return constructCommonWorkFlow(entity.getCreateEmpNo(),
                () -> hrmResourceService.getHrmServiceEmpInfoByCode(entity.getEmpNo()),
                (targetItem, targetCreatorId) -> buildLeaveFormRequestInfo(targetItem, targetCreatorId, entity)
        );
    }

    /**
     * 构建预算表单工作流
     *
     * @param entity 实体
     * @return {@link String }
     */
    @Override
    public String constructBudgetFormWorkFlow(ErpBudgetResultVo entity) {
        return constructCommonWorkFlow(entity.getBudgetManagerCode(),
                () -> hrmResourceService.getHrmServiceEmpInfoByCode(entity.getBudgetManagerCode()),
                (targetItem, targetCreatorId) -> buildBudgetRequestInfo(entity, targetCreatorId)
        );
    }

    /**
     * 根据给定的组织机构实体列表，构建组织工作流。
     *
     * @param list 组织机构实体列表，包含待处理的组织信息。
     * @return 返回组织工作流构建的结果字符串。
     */
    @Override
    public String constructOrgWorkflow(List<DhgOrgEntity> list) {
        // 初始化用于拼接部门代码的字符串构建器
        String resDeptCodeStr;
        // 初始化最终结果列表
        List<OAOrgEntity> resList = new ArrayList<>();
        // 初始化待添加领导的列表
        List<OAOrgEntity> addLeaderList = new ArrayList<>();

        try {

            // 获取所有子公司的映射，键为代码，值为实体
            Map<String, SubCompanyBean> allSubcompanyMap = Arrays.stream(hrmResourceService.getAllSubCompanyList())
                    .filter(item -> StrUtil.isNotEmpty(item.get_code()))
                    .collect(Collectors.toMap(SubCompanyBean::get_code, item -> item, (first, second) -> first));
            // 获取所有部门的映射，键为代码，值为实体
            Map<String, DepartmentBean> allDepartmentMap = Arrays.stream(hrmResourceService.getAllDepartmentList())
                    .filter(item -> StrUtil.isNotEmpty(item.get_code()))
                    .collect(Collectors.toMap(DepartmentBean::get_code, item -> item, (first, second) -> first));

            // 遍历输入的组织机构实体列表
            for (DhgOrgEntity entity : list) {
                if (StrUtil.isNotEmpty(entity.code())) {
                    OAOrgEntity oaOrgEntity = new OAOrgEntity();
                    // 根据实体的failure字段判断操作类型
                    if (0 == entity.isFailure()) {
                        // 如果该实体对应的部门或子公司在映射中不存在，则为新增操作
                        if (!allDepartmentMap.containsKey(entity.code()) && !allSubcompanyMap.containsKey(entity.code())) {
                            oaOrgEntity = oaOrgEntity.action(OAHrmTemplateUtil.ADD)
                                    .code(entity.code())
                                    .shortname(entity.shortName())
                                    .fullname(entity.fullName())
                                    .parent_code(entity.parentCode())
                                    .org_code(entity.companyCode())
                                    .order(entity.showOrder())
                                    .isCompany(entity.isCompany())
                                    .leaderCode(entity.leaderCode())
                                    .canceled(entity.isFailure());
                            addLeaderList.add(oaOrgEntity);
                        } else {
                            if (Objects.equals(allDepartmentMap.get(entity.code()).get_canceled(), "1")) {
                                // 如果原本状态为封存，直接解封就ok了
                                oaOrgEntity = oaOrgEntity.action(OAHrmTemplateUtil.DELETE)
                                        .code(entity.code())
                                        .shortname(entity.shortName())
                                        .isCompany(entity.isCompany())
                                        .canceled(1);
                            } else {
                                // 如果已存在，则为编辑操作
                                oaOrgEntity = oaOrgEntity.action(OAHrmTemplateUtil.EDIT)
                                        .code(entity.code())
                                        .shortname(entity.shortName())
                                        .fullname(entity.fullName())
                                        .parent_code(entity.parentCode())
                                        .org_code(entity.companyCode())
                                        .isCompany(entity.isCompany())
                                        .leaderCode(entity.leaderCode())
                                        .order(entity.showOrder());
                            }
                            addLeaderList.add(oaOrgEntity);
                        }

                    } else {
                        // 如果failure为非0，表示删除操作
                        oaOrgEntity = oaOrgEntity.action(OAHrmTemplateUtil.DELETE)
                                .code(entity.code())
                                .shortname(entity.shortName())
                                .isCompany(entity.isCompany())
                                .canceled(0);

                    }
                    // 将处理后的实体添加到最终结果列表中
                    resList.add(oaOrgEntity);
                }
            }

            // 处理同步组织架构的事情
            resDeptCodeStr = dealSyncCompOrDeptStrings(resList);


            // 构建部门负责人新增的请求列表
            List<OADeptAndLeaderEntity> formBuildList = new ArrayList<>();
            for (OAOrgEntity oaOrgEntity : addLeaderList) {
                String deptId = hrmResourceService.getHrmServiceDepartmentByCode(oaOrgEntity.code());
                if (StrUtil.isNotEmpty(oaOrgEntity.leaderCode())) {
                    if (StrUtil.contains(oaOrgEntity.leaderCode(), ";")) {
                        List<String> leaderCodeList = StrUtil.split(oaOrgEntity.leaderCode(), ";");
                        for (String leaderCode : leaderCodeList) {
                            fillEntityFormList(formBuildList, deptId, leaderCode);
                        }
                    } else {
                        fillEntityFormList(formBuildList, deptId, oaOrgEntity.leaderCode());
                    }
                }
            }

            // 如果列表为空，表示没有需要提交的流程表单
            if (formBuildList.isEmpty()) {
                return "不存在流程表单的提交！完成的部门的code为：" + resDeptCodeStr;
            }

            // 构建流程请求信息
            WorkflowRequestInfo requestInfo = buildOrgChangeRequestInfo(formBuildList);
            // 提交流程请求，并返回结果
            return workFlowService.secondBuildFormRequest(requestInfo, workflowFormProperties.getCreator());
        } catch (Exception e) {
            log.error("constructOrgWorkflow发生了错误：{}", e.getMessage(), e);
            return "构建组织架构调整单失败了，可能同步组织架构或者单据出现问题，请仔细检查任务参数后再提交！";
        }
    }

    @Override
    public String testConstructFlow(List<OADeptAndLeaderEntity> list) {

        WorkflowRequestInfo requestInfo = buildOrgChangeRequestInfo(list);
        return workFlowService.secondBuildFormRequest(requestInfo, workflowFormProperties.getCreator());
    }


    /**
     * 构建通用工作流
     *
     * @param creatorEmpNo       创建人工号
     * @param targetBeanSupplier 供应商-> 提供创建对象信息
     * @param function           函数 -> 提供构建的WorkflowRequestInfo 实体对象
     * @return {@link String }
     */
    private String constructCommonWorkFlow(String creatorEmpNo,
                                           Supplier<UserBean> targetBeanSupplier, BiFunction<UserBean, Integer, WorkflowRequestInfo> function) {
        try {

            // 获取到发起人id
            UserBean createdUserBean = hrmResourceService.getHrmServiceEmpInfoByCode(creatorEmpNo);
            // 构建请求参数
            WorkflowRequestInfo requestInfo = function.apply(targetBeanSupplier.get(), createdUserBean.getUserid());

            // 提交表单请求
            return workFlowService.secondBuildFormRequest(requestInfo, createdUserBean.getUserid());
        } catch (Exception e) {

            return e.getMessage();
        }
    }


    /**
     * 构建入职请求信息
     *
     * @param userBean      用户bean
     * @param workStartDate 工作开始日期
     * @param isAttendance  是出席
     * @return {@link WorkflowRequestInfo }
     */
    private WorkflowRequestInfo buildOnboardingRequestInfo(UserBean userBean, Integer userId, String workStartDate, String isAttendance) {
        OAEmployeeEntity oaEmployee = new OAEmployeeEntity()
                .employeeId(userBean.getUserid().toString())
                // 新增empName方便日志查询
                .empName(userBean.getLastname())
                .code(userBean.getWorkcode())
                .departmentId(userBean.getDepartmentid())
                .companyId(userBean.getSubcompanyid1())
                .workPlace("")
                .workStartDate(workStartDate)
                .phoneNumber(userBean.getMobile())
                .isChecked(isAttendance)
                .emailAddress("")
                .postId(userBean.getJobtitle())
                .createdBy("自动创建")
                .reqDate(DateUtil.date().toDateStr());

        Map<String, Object> mainTableMap = OACommonEntityUtil.buildEntityToParamMap(oaEmployee);
        log.info("mainTableMap = {}", mainTableMap);
        XxlJobHelper.log("OAEmployeeEntity = {},\n mainTableMap = {}", oaEmployee, mainTableMap);
        return oaCommonEntityUtil.buildWorkflowRequestInfo(WorkflowEnum.ON_BOARDING_FORM_FLOW, mainTableMap, userId);
    }


    /**
     * 构建转岗流转单请求
     *
     * @param userBean 用户bean
     * @param entity   dhg的实体
     * @return {@link WorkflowRequestInfo }
     */
    private WorkflowRequestInfo buildTransFormRequestInfo(UserBean userBean, Integer creatorId,
                                                          DhgEmployeeTransEntity entity) {
        String newPostCode = entity.newPostCode();
        String newDeptCode = entity.newDeptCode();
        String newCompanyCode = entity.newCompanyCode();

        String jobTitleId = hrmResourceService.getHrmServiceJobTitleIdByCode(newPostCode);
        String orgId = hrmResourceService.getHrmServiceSubCompanyByCode(newCompanyCode);
        String deptId = hrmResourceService.getHrmServiceDepartmentByCode(newDeptCode);
        String leaderCode = entity.newLeaderNo();
        UserBean leader = hrmResourceService.getHrmServiceEmpInfoByCode(leaderCode);

        Opt.ofNullable(leader).orElseThrow(() -> new RuntimeException("该员工上级在oa中不存在！请检查！"));

        Opt.ofNullable(userBean).orElseThrow(() -> new RuntimeException("在oa中，该员工不存在！请检查！"));
        // 原部门id
        String sourceLeaderId = userBean.getManagerid();
        Opt.ofNullable(sourceLeaderId).orElseThrow(() -> new RuntimeException("在oa中，该员工上原部门上级不存在！请检查！"));

        String changeType;
        // 新增逻辑,比较处理流动类型(直接对比id)
        if (!StrUtil.equals(orgId, userBean.getSubcompanyid1())) {
            // 公司变动
            changeType = "0";
        } else if (!StrUtil.equals(deptId, userBean.getDepartmentid())) {
            // 部门调整
            changeType = "1";
        } else if (!StrUtil.equals(leader.getUserid().toString(), sourceLeaderId)) {
            // 领导变动
            changeType = "2";
        } else if (!StrUtil.equals(jobTitleId, userBean.getJobtitle())) {
            // 岗位变动
            changeType = "3";
        } else {
            throw new RuntimeException("请确定此转岗单有以下的变动类型  1、公司变动 2、部门调整 3、领导变动 4、岗位变动");
        }

        OAEmployeeTransEntity oaEmployee = new OAEmployeeTransEntity()
                .userId(userBean.getUserid().toString())
                .empCode(userBean.getWorkcode())
                .oldDept(userBean.getDepartmentid())
                .oldCompany(userBean.getSubcompanyid1())
                .oldPost(userBean.getJobtitle())
                .transTime(entity.flowDate())
                .newPost(jobTitleId)
                .newCompany(orgId)
                .newDept(deptId)
                .originEmail(userBean.getEmail())
                .createdBy("自动创建")
                .reason(entity.reason())
                .newLeadId(leader.getUserid().toString())
                .reqDate(DateUtil.date().toDateStr())
                .changeType(changeType);

        Map<String, Object> mainTableMap = OACommonEntityUtil.buildEntityToParamMap(oaEmployee);
        log.info("OAEmployeeTransEntity = {},\n mainTableMap = {}", oaEmployee, mainTableMap);
        XxlJobHelper.log("OAEmployeeTransEntity = {},\n mainTableMap = {}", oaEmployee, mainTableMap);
        return oaCommonEntityUtil.buildWorkflowRequestInfo(WorkflowEnum.POST_TRANSFER_FORM_FLOW, mainTableMap, creatorId);
    }


    /**
     * 构建休假表单请求信息
     *
     * @param userBean 用户bean
     * @param entity   实体
     * @return {@link WorkflowRequestInfo }
     */
    private WorkflowRequestInfo buildLeaveFormRequestInfo(UserBean userBean, Integer creatorId, DhgEmployeeLeaveEntity entity) {
        if (ObjectUtil.isNull(userBean)) {
            throw new RuntimeException(entity.getEmpNo() + "人员在OA中已经失效了！新增流程失败！");
        }
        String sex = Objects.requireNonNull(userBean.getSex()).equals("男") ? "0" : "1";
        OAEmployeeLeaveEntity oaEmployee = new OAEmployeeLeaveEntity()
                .leaveDate(entity.leaveDate())
                .empCode(entity.getEmpNo())
                .sex(sex)
                .email(userBean.getEmail())
                .employeeId(userBean.getUserid().toString())
                .companyId(userBean.getSubcompanyid1())
                .postId(userBean.getJobtitle())
                .departmentId(userBean.getDepartmentid())
                .reqDate(DateUtil.date().toDateStr())
                .createdBy("自动创建");


        Map<String, Object> mainTableMap = OACommonEntityUtil.buildEntityToParamMap(oaEmployee);
        log.info("OAEmployeeLeaveEntity = {},\n mainTableMap = {}", oaEmployee, mainTableMap);
        XxlJobHelper.log("OAEmployeeLeaveEntity = {},\n mainTableMap = {}", oaEmployee, mainTableMap);
        return oaCommonEntityUtil.buildWorkflowRequestInfo(WorkflowEnum.RESIGN_FORM_FLOW, mainTableMap, creatorId);

    }


    /**
     * 构建组织变更请求信息
     *
     * @param list 列表
     * @return {@link WorkflowRequestInfo }
     */
    private WorkflowRequestInfo buildOrgChangeRequestInfo(List<OADeptAndLeaderEntity> list) {

        List<Map<String, Object>> results = new ArrayList<>();
        for (OADeptAndLeaderEntity entity : list) {
            Map<String, Object> map = OACommonEntityUtil.buildEntityToParamMap(entity);
            results.add(map);
        }

        XxlJobHelper.log("results = {}", results);
        return oaCommonEntityUtil.buildWorkflowRequestInfo(WorkflowEnum.ORG_CHANGE_FORM_FLOW, workflowFormProperties.getCreator(), new HashMap<>(), results);
    }


    /**
     * 构建预算表单请求信息
     *
     * @param main 主要
     * @return {@link WorkflowRequestInfo }
     */
    private WorkflowRequestInfo buildBudgetRequestInfo(ErpBudgetResultVo main, Integer creatorId) {
        String budgetDeptId = main.getBudgetDeptId();
        String budgetManagerCode = main.getBudgetManagerCode();
        String budgetCompanyCode = main.getBudgetCompanyCode();
        String consecutivePeriod = main.getConsecutivePeriod();
        try {
            // 公司id
            String companyId = oaCompanyService.getOACompanyByReflectCode(budgetCompanyCode);
            // 预算负责人id
            UserBean manager = hrmResourceService.getHrmServiceEmpInfoByCode(budgetManagerCode);
            Opt.ofNullable(manager).orElseThrow(() -> new RuntimeException("该预算负责人不存在！请检查！"));
            // 主表数据
            OABudgetMainEntity mainEntity = new OABudgetMainEntity()
                    .applyDate(DateUtil.format(DateUtil.date(), DatePattern.NORM_DATE_PATTERN))
                    .consecutivePeriod(consecutivePeriod)
                    .budgetCompanyId(companyId)
                    .budgetDeptId(budgetDeptId)
                    .budgetManagerId(manager.getUserid().toString());
            // 构建主表明细项
            Map<String, Object> mainMap = OACommonEntityUtil.buildEntityToParamMap(mainEntity);
            // 构建明细表数据
            List<ErpBudgetDetailEntity> detail = main.getDetailList();
            List<Map<String, Object>> detailList = new ArrayList<>();
            for (ErpBudgetDetailEntity entity : detail) {

                BigDecimal periodsUsageRate = new BigDecimal(entity.getPeriodsUsageRate());
                BigDecimal divided;
                if (periodsUsageRate.compareTo(BigDecimal.ZERO) == 0) {
                    divided = BigDecimal.ZERO;
                } else {
                    divided = periodsUsageRate.divide(BigDecimal.valueOf(100), 12, RoundingMode.HALF_UP);
                }
                entity.setPeriodsUsageRate(divided.toPlainString());
                Map<String, Object> map = OACommonEntityUtil.buildEntityToParamMap(entity);
                detailList.add(map);
            }
            return oaCommonEntityUtil.buildWorkflowRequestInfo(WorkflowEnum.ERP_BUDGET_FORM_FLOW, creatorId, mainMap, detailList);
        } catch (Exception e) {
            log.error("制作预算审批单失败了：{}", e.getMessage(), e);
            throw new RuntimeException(e);
        }

    }

    /**
     * 填充实体类的单据
     *
     * @param formBuildList 表单构建列表
     * @param deptId        部门id
     * @param leaderCode    领袖代码
     */
    private void fillEntityFormList(List<OADeptAndLeaderEntity> formBuildList, String deptId, String leaderCode) {
        UserBean userBean = hrmResourceService.getHrmServiceEmpInfoByCode(leaderCode);
        if (userBean != null) {
            String leaderId = userBean.getUserid().toString();
            OADeptAndLeaderEntity oaDeptAndLeader = new OADeptAndLeaderEntity()
                    .deptId(deptId)
                    .leaderId(leaderId);
            formBuildList.add(oaDeptAndLeader);
        }
    }


    /**
     * 处理同步公司或部门拼接的字符串
     *
     * @param list 列表
     * @return {@link String }
     */
    private String dealSyncCompOrDeptStrings(List<OAOrgEntity> list) {
        StringBuilder result = new StringBuilder();
        StringBuilder finishedCode = new StringBuilder();
        boolean success = true;
        for (OAOrgEntity oaOrgEntity : list) {
            String parsedStr = OAHrmTemplateUtil.parseEntityXml(oaOrgEntity, "org", "isCompany", "leaderCode");
            // 处理公司部门相关信息
            if (!parsedStr.isEmpty()) {
                String entity = OAHrmTemplateUtil.getHrmOrgInfoTemplateStr(parsedStr);
                try {
                    String singleRes;
                    if (1 == oaOrgEntity.isCompany()) {
                        // 处理公司相关信息
                        singleRes = hrmResourceService.syncHrmCompany(entity);
                    } else {
                        // 处理部门相关信息
                        singleRes = hrmResourceService.syncDepartment(entity);
                    }
                    result.append(sbResult2String(parsedStr))
                            .append("\n")
                            .append("操作结果：")
                            .append(singleRes)
                            .append("\n");
                } catch (Exception e) {
                    success = false;
                    result.append(sbResult2String(parsedStr))
                            .append("\n")
                            .append("<p style='color:red'>")
                            .append(sbResult2String(e.getMessage()))
                            .append("</p>")
                            .append("\n");
                }
            }
            finishedCode.append(oaOrgEntity.code()).append(",");
        }

        XxlJobHelper.log("参数以及执行结果:\n{}", result.toString());
        if (!success) {
            mailUtil.sendSimpleMail("组织架构调整单 同步组织架构失败", result.toString());
            throw new RuntimeException(result.toString());
        }
        return finishedCode.toString();
    }

    /**
     * Sb result2字符串
     *
     * @param result 结果
     * @return {@link String }
     */
    private String sbResult2String(String result) {
        return result.replaceAll("<", "&lt").replaceAll(">", "&gt");
    }

}
